﻿using System.Linq;
using System.Threading;
using Common.Logging;
using Out.Service.Services;
using Rmq.Center;

namespace Out.TaskRunner.RmqWorkers
{
    public class OrderRefundingWorker : IWorker
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(OrderRefundingWorker));

        public void Start(CancellationToken ct)
        {
            if (ct.IsCancellationRequested)
            {
                return;
            }

            using (var consumer = new OrderRefundingConsumer())
            {
                consumer.Subscribe((id, count, dt, msg, channel) =>
                {
                    if (msg.OrderType == OrderType.挂号订单)
                    {
                        return ProcessRegOrder(msg.OrderId, msg.Reason, msg.OrderStatus, channel);
                    }
                    else if (msg.OrderType == OrderType.门诊缴费订单)
                    {
                        //处理门诊缴费单退费
                        return ProcessBillOrder(msg.OrderId, msg.Reason, msg.OrderStatus, channel);
                    }
                    else if (msg.OrderType == OrderType.住院预缴金订单)
                    {
                        //住院预缴金订单退费
                        return ProcessInpatientPrepayOrder(msg.OrderId, msg.Reason, msg.OrderStatus, channel);
                    }

                    return new ConsumedResult { Ack = true };
                });

                while (true)
                {
                    if (ct.IsCancellationRequested)
                    {
                        break;
                    }

                    Thread.Sleep(50);
                }
            }
        }

        private ConsumedResult ProcessRegOrder(int orderId, int reason, int[] orderStatus, WrapperChannel channel)
        {
            using (var orderCtx = new BizApptOrder(orderId))
            {
                var order = orderCtx.Get();
                if (orderStatus.Length <= 0 || orderStatus.Any(x => x == order.OrderStatus))
                {
                    var result = orderCtx.Refunding((BizApptOrder.RefundReason) reason);
                    if (result.Result == Result.未返回)
                    {
                        return new ConsumedResult
                        {
                            Ack = false,
                            Delay = 1000
                        };
                    }
                }
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }

        private ConsumedResult ProcessBillOrder(int orderId, int reason, int[] orderStatus, WrapperChannel channel)
        {
            using (var orderCtx = new BizBillOrder(orderId))
            {
                var order = orderCtx.GetBillOrder();
                if (orderStatus.Length <= 0 || orderStatus.Any(x => x == order.OrderStatus))
                {
                    var result = orderCtx.Refunding();
                    if (result.Result == Result.未返回)
                    {
                        return new ConsumedResult
                        {
                            Ack = false,
                            Delay = 1000
                        };
                    }
                }
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }

        private ConsumedResult ProcessInpatientPrepayOrder(int orderId, int reason, int[] orderStatus, WrapperChannel channel)
        {
            using (var orderCtx = new BizInpatientPrepayOrder(orderId))
            {
                var order = orderCtx.Get();
                if (orderStatus.Length <= 0 || orderStatus.Any(x => x == order.OrderStatus))
                {
                    var result = orderCtx.Refunding();
                    if (result.Result == Result.未返回)
                    {
                        return new ConsumedResult
                        {
                            Ack = false,
                            Delay = 1000
                        };
                    }
                }
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }
    }
}